[IA64] fix ptc.ga virtualization
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Mon, 19 Jun 2006 19:45:42 +0000 (13:45 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Mon, 19 Jun 2006 19:45:42 +0000 (13:45 -0600)
fix ptc.ga virtualization. Uninitialized vcpu doesn't need tlb flush.
ptc_ga_remote_func() calls vmx_vcpu_ptc_l() in IPI context.
I.e. vcpu may not equal to current. On the other hand vmx_vcpu_ptc_l()
assumes vcpu = current. remove the assumption.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
xen/arch/ia64/vmx/vmmu.c
xen/arch/ia64/vmx/vmx_phy_mode.c
xen/arch/ia64/vmx/vtlb.c
xen/arch/ia64/xen/regionreg.c
xen/arch/ia64/xen/vhpt.c
xen/include/asm-ia64/regionreg.h
xen/include/asm-ia64/vmx.h
xen/include/asm-ia64/vmx_phy_mode.h

index 47d3f47b549588e963ac7e026f7420f82dcb6d6a..df55aea9ef5de527f368a004b902ef832333865b 100644 (file)
@@ -544,6 +544,9 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu,UINT64 va,UINT64 ps)
     vcpu_get_rr(vcpu, va, &args.rid);
     args.ps = ps;
     for_each_vcpu (d, v) {
+        if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+            continue;
+
         args.vcpu = v;
         if (v->processor != vcpu->processor) {
             int proc;
index 0ce402018acd59863ae1be61e80d5b0540a091d9..52825720e0cb3faa588db7ebfd93471f46d9e1d5 100644 (file)
@@ -137,13 +137,14 @@ vmx_init_all_rr(VCPU *vcpu)
 #endif
 }
 
+extern void * pal_vaddr;
+
 void
 vmx_load_all_rr(VCPU *vcpu)
 {
        unsigned long psr;
        ia64_rr phy_rr;
 
-       extern void * pal_vaddr;
        local_irq_save(psr);
 
 
@@ -203,6 +204,24 @@ vmx_load_all_rr(VCPU *vcpu)
        ia64_srlz_i();
 }
 
+void
+vmx_load_rr7_and_pta(VCPU *vcpu)
+{
+       unsigned long psr;
+
+       local_irq_save(psr);
+
+       vmx_switch_rr7(vrrtomrr(vcpu,VMX(vcpu, vrr[VRN7])),
+                       (void *)vcpu->domain->shared_info,
+                       (void *)vcpu->arch.privregs,
+                       (void *)vcpu->arch.vhpt.hash, pal_vaddr );
+       ia64_set_pta(vcpu->arch.arch_vmx.mpta);
+
+       ia64_srlz_d();
+       local_irq_restore(psr);
+       ia64_srlz_i();
+}
+
 void
 switch_to_physical_rid(VCPU *vcpu)
 {
index 6ac72f9d5ca79c829b0f9a2fc52d4258bfede798..ba6bce42cac997ce0783b4b701146df694c9d07c 100644 (file)
 #include <asm/gcc_intrin.h>
 #include <linux/interrupt.h>
 #include <asm/vmx_vcpu.h>
+#include <asm/vmx_phy_mode.h>
 #include <asm/vmmu.h>
 #include <asm/tlbflush.h>
+#include <asm/regionreg.h>
 #define  MAX_CCH_LENGTH     40
 
 thash_data_t *__alloc_chain(thash_cb_t *);
@@ -229,12 +231,13 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
  *  purge software guest tlb
  */
 
-static void vtlb_purge(thash_cb_t *hcb, u64 va, u64 ps)
+static void vtlb_purge(VCPU *v, u64 va, u64 ps)
 {
+    thash_cb_t *hcb = &v->arch.vtlb;
     thash_data_t *hash_table, *prev, *next;
     u64 start, end, size, tag, rid, def_size;
     ia64_rr vrr;
-    vcpu_get_rr(current, va, &vrr.rrval);
+    vcpu_get_rr(v, va, &vrr.rrval);
     rid = vrr.rid;
     size = PSIZE(ps);
     start = va & (-size);
@@ -263,16 +266,29 @@ static void vtlb_purge(thash_cb_t *hcb, u64 va, u64 ps)
     }
 //    machine_tlb_purge(va, ps);
 }
+
+static void
+switch_rr7_and_pta(VCPU* v)
+{
+    if (VMX_DOMAIN(v))
+        vmx_load_rr7_and_pta(v);
+    else
+        load_region_reg7_and_pta(v);
+}
+
 /*
  *  purge VHPT and machine TLB
  */
-static void vhpt_purge(thash_cb_t *hcb, u64 va, u64 ps)
+static void vhpt_purge(VCPU *v, u64 va, u64 ps)
 {
+    //thash_cb_t *hcb = &v->arch.vhpt;
     thash_data_t *hash_table, *prev, *next;
     u64 start, end, size, tag;
     size = PSIZE(ps);
     start = va & (-size);
     end = start + size;
+    if (current != v)
+        switch_rr7_and_pta(v);
     while(start < end){
         hash_table = (thash_data_t *)ia64_thash(start);
         tag = ia64_ttag(start);
@@ -294,6 +310,8 @@ static void vhpt_purge(thash_cb_t *hcb, u64 va, u64 ps)
         start += PAGE_SIZE;
     }
     machine_tlb_purge(va, ps);
+    if (current != v)
+        switch_rr7_and_pta(current);
 }
 
 /*
@@ -413,8 +431,8 @@ int vtr_find_overlap(VCPU *vcpu, u64 va, u64 ps, int is_data)
 void thash_purge_entries(VCPU *v, u64 va, u64 ps)
 {
     if(vcpu_quick_region_check(v->arch.tc_regions,va))
-        vtlb_purge(&v->arch.vtlb, va, ps);
-    vhpt_purge(&v->arch.vhpt, va, ps);
+        vtlb_purge(v, va, ps);
+    vhpt_purge(v, va, ps);
 }
 
 u64 translate_phy_pte(VCPU *v, u64 *pte, u64 itir, u64 va)
@@ -456,17 +474,17 @@ void thash_purge_and_insert(VCPU *v, u64 pte, u64 itir, u64 ifa)
         phy_pte = translate_phy_pte(v, &pte, itir, ifa);
         if(ps==PAGE_SHIFT){
             if(!(pte&VTLB_PTE_IO)){
-                vhpt_purge(&v->arch.vhpt, ifa, ps);
+                vhpt_purge(v, ifa, ps);
                 vmx_vhpt_insert(&v->arch.vhpt, phy_pte, itir, ifa);
             }
             else{
-                vhpt_purge(&v->arch.vhpt, ifa, ps);
+                vhpt_purge(v, ifa, ps);
                 vtlb_insert(&v->arch.vtlb, pte, itir, ifa);
                 vcpu_quick_region_set(PSCBX(v,tc_regions),ifa);
             }
         }
         else{
-            vhpt_purge(&v->arch.vhpt, ifa, ps);
+            vhpt_purge(v, ifa, ps);
             vtlb_insert(&v->arch.vtlb, pte, itir, ifa);
             vcpu_quick_region_set(PSCBX(v,tc_regions),ifa);
             if(!(pte&VTLB_PTE_IO)){
index 58c89201fbe6739ca886025239703802bfe42294..e51485190e63d05be49adb4e77f899e4ba39c5c1 100644 (file)
@@ -342,3 +342,16 @@ void load_region_regs(struct vcpu *v)
                panic_domain(0,"load_region_regs: can't set! bad=%lx\n",bad);
        }
 }
+
+void load_region_reg7_and_pta(struct vcpu *v)
+{
+       unsigned long rr7;
+
+       ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
+                    VHPT_ENABLED);
+
+       // TODO: These probably should be validated
+       rr7 =  VCPU(v,rrs[7]);
+       if (!set_one_rr(0xe000000000000000L, rr7))
+               panic_domain(0, "%s: can't set!\n", __func__);
+}
index 0d037fdb2575f8f0434314d0cfcf3d5f04cb713c..0a653d173aaf3f198875058e69f98a6670d2b830 100644 (file)
@@ -153,7 +153,10 @@ void domain_flush_vtlb_all (void)
        int cpu = smp_processor_id ();
        struct vcpu *v;
 
-       for_each_vcpu (current->domain, v)
+       for_each_vcpu (current->domain, v) {
+               if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+                       continue;
+
                if (v->processor == cpu)
                        vcpu_flush_vtlb_all ();
                else
@@ -161,6 +164,7 @@ void domain_flush_vtlb_all (void)
                                (v->processor,
                                 (void(*)(void *))vcpu_flush_vtlb_all,
                                 NULL,1,1);
+       }
 }
 
 static void cpu_flush_vhpt_range (int cpu, u64 vadr, u64 addr_range)
@@ -198,6 +202,9 @@ void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range)
 #endif
 
        for_each_vcpu (d, v) {
+               if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+                       continue;
+
                /* Purge TC entries.
                   FIXME: clear only if match.  */
                vcpu_purge_tr_entry(&PSCBX(v,dtlb));
@@ -206,6 +213,9 @@ void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range)
        smp_mb();
 
        for_each_vcpu (d, v) {
+               if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+                       continue;
+
                /* Invalidate VHPT entries.  */
                cpu_flush_vhpt_range (v->processor, vadr, addr_range);
        }
index c2e9ecc68266bc5401ea89a997b42f0dcb337261..7b9baecd9e0f280ebba5907a51470d80efdac347 100644 (file)
@@ -79,5 +79,6 @@ extern void init_all_rr(struct vcpu *v);
 extern int set_metaphysical_rr0(void);
 
 extern void load_region_regs(struct vcpu *v);
+extern void load_region_reg7_and_pta(struct vcpu *v);
 
 #endif         /* !_REGIONREG_H_ */
index 99ffb7b7ab0a895f886b79a42309cd0588c47a35..3e07a6c32d75982a1bbf0d9fcb739c203a3f4b27 100644 (file)
@@ -37,7 +37,6 @@ extern void vmx_load_state(struct vcpu *v);
 extern void vmx_setup_platform(struct domain *d, struct vcpu_guest_context *c);
 extern void vmx_wait_io(void);
 extern void vmx_io_assist(struct vcpu *v);
-extern void vmx_load_all_rr(struct vcpu *vcpu);
 extern void panic_domain(struct pt_regs *regs, const char *fmt, ...);
 extern int ia64_hypercall (struct pt_regs *regs);
 extern void vmx_save_state(struct vcpu *v);
index 02f8cc643fa34a035fe5fc1ece577914f3bb52f2..c480d11dfcea27713ec19df8f12c9d810261369f 100644 (file)
@@ -96,6 +96,7 @@ extern void prepare_if_physical_mode(VCPU *vcpu);
 extern void recover_if_physical_mode(VCPU *vcpu);
 extern void vmx_init_all_rr(VCPU *vcpu);
 extern void vmx_load_all_rr(VCPU *vcpu);
+extern void vmx_load_rr7_and_pta(VCPU *vcpu);
 extern void physical_tlb_miss(VCPU *vcpu, u64 vadr);
 /*
  * No sanity check here, since all psr changes have been